const fs = require('fs')
const path = require('path')

const fileUtils = {
  // 文件存在性
  exists (filePath) {
    return new Promise((resolve, reject) => {
      // access函数的第二个参数为fs.constants.F_OK时，用于检测文件存在性
      fs.access(filePath, fs.constants.F_OK, (err) => {
        if (err) {
          // 文件不存在
          resolve(false)
        }
        else {
          resolve(true)
        }
      })
    })
  },
  
  // 创建文件夹
  createFolder: async (folderPath) => {
    const isExists = await fileUtils.exists(folderPath)
    if (isExists) {
      return
    }
    // fs.promises中的方法均为Promises
    await fs.promises.mkdir(folderPath)
  },
  
  // 删除路径
  deleteDir: async (filePath) => {
    // 先判断文件是否存在
    const isExists = await fileUtils.exists(filePath)
    if (!isExists) {
      // 文件不存在，不用删除
      return
    }
    // 文件存在，先获取文件信息
    const stat = await fs.promises.stat(filePath)
    if (stat.isFile()) {
      // 如果路径是文件，直接删除
      // console.log('删除文件: ' + filePath)
      await fs.promises.unlink(filePath)
      return
    }
    
    let dirs = await fs.promises.readdir(filePath)
    const len = dirs.length
    if (len === 0) {
      // 删掉空目录
      await fs.promises.rmdir(filePath)
      return
    }
    
    dirs = dirs.map((dir) => {
      let dirPath = path.join(filePath, dir)
      // async函数返回的是Promise对象，这样就凑成了进程数组，后续可以使用Promise.all
      return fileUtils.deleteDir(dirPath)
    })
    
    const timeout = (time) => {
      return new Promise((resolve, reject) => {
        setTimeout(() => {
          resolve()
        }, time)
      })
    }
    
    await Promise.all(dirs)
    // 如果不设置一些延迟,则会报错
    await timeout(50)
    // 删除所有文件以后，删除空目录
    // console.log('删除空目录: ' + filePath)
    await fs.promises.rmdir(filePath)
  },
  
  /* 
    拷贝路径
    source 拷贝的原路径
    des 拷贝的去处(不包含原路径名称)
    如source = /a  des = /b  则最终路径 /b/a
  */
  async copyDir (source, des) {
    // 判断源路径是否存在
    const sourceExists = await fileUtils.exists(source)
    if (!sourceExists) {
      // 不存在，不用拷贝
      return
    }

    // 判断目标路径是否存在
    const desExists = await fileUtils.exists(des)
    if (!desExists) {
      // 不存在，不用拷贝
      return
    }   
   
    // 文件存在，先获取文件信息
    const stat = await fs.promises.stat(source)
    // 获取文件名,进而获取完整的目标路径
    const name = path.basename(source)
    const desPath = path.join(des, name)
    if (stat.isFile()) {
      // 如果路径是文件，直接拷贝过去
      await fs.promises.copyFile(source, desPath)
      return
    }
    
    // 不是文件说明是目录
    let dirs = await fs.promises.readdir(source)
    // 在目标处也创建同名目录
    await fileUtils.createFolder(desPath)
    const len = dirs.length
    if (len === 0) {
      // 空目录
      return
    }
    
    // 不是空目录,则对目录下的每一个文件递归使用
    dirs = dirs.map((dir) => {
      let sourcePath = path.join(source, dir)
      // async函数返回的是Promise对象，这样就凑成了进程数组，后续可以使用Promise.all
      return fileUtils.copyDir(sourcePath, desPath)
    })
    
    await Promise.all(dirs)
  },
  
  // 文件名去除后缀
  cutFileTail (name) {
    let arr = name.split('.')
    arr.splice(arr.length - 1, 1)
    return arr.join('.')
  },
  
  // 获取后缀
  getFileTail (name) {
    let arr = name.split('.')
    return arr[arr.length - 1]
  },
  
  // 从路径中获取最后一个/后的字符串
  // 暂时不改了, 但是也不要用了,以后用path.basename()
  getLastName (name) {
    let key = '/'
    let arr = name.split(key)
    const len = arr.length
    let index = len - 1
    let lastName = arr[index]
    while (lastName === key && index > 0) {
      index--
      lastName = arr[index]
    }
    return lastName
  }
}

module.exports = fileUtils